#ifndef _M_BUFFER_H__
#define _M_BUFFER_H__

/*实现异步日志器缓冲区*/

#include "util.hpp"
#include <vector>
#include <cassert>

namespace Yohifo
{
#define DEFAULT_BUFFER_SIZE (32 * 1024 * 1024) // 默认大小
#define DEFAULT_THRESHOLD (128 * 1024 * 1024)  // 默认阈值
#define LINEAR_GROWTH (32 * 1024 * 1024)       // 单次线性增长的大小

    class Buffer
    {
    public:
        // 默认大小为 32MB
        Buffer(size_t size = DEFAULT_BUFFER_SIZE)
            : _buffer(size), _write_idx(0), _read_idx(0)
        {
        }

        // 写入数据
        void Push(const char *data, size_t len)
        {
            // Buffer 不需要考虑该[扩容]还是该[阻塞]
            ExpansionEnoughSize(len);

            // 利用函数 copy 将数据拷贝至 _buffer
            std::copy(data, data + len, &(_buffer[_write_idx]));

            // 移动（可写入位置向后偏移）
            RemoveWrite(len);
        }

        // 获取可读取数据位置的起始地址
        const char *Begin()
        {
            return &_buffer[_read_idx];
        }

        // 获取可写入空间大小
        size_t WriteableSize()
        {
            // 线性增长的空间，可以直接相减
            return (_buffer.size() - _write_idx);
        }

        // 获取可读取数据长度
        size_t ReadbleSize()
        {
            // 线性增长的空间，可以直接相减
            return (_write_idx - _read_idx);
        }

        // 对读取数据指针进行移动
        void RemoveRead(size_t len)
        {
            // 要求：移动范围不能超过可读范围
            assert(len <= ReadbleSize());

            _read_idx += len;
        }

        // 初始化缓冲区
        void InitBuffer()
        {
            // 读/写 置为 0
            _write_idx = _read_idx = 0;
        }

        // 交换缓冲区
        void Swap(Buffer &buffer)
        {
            // 交换缓冲区、读指针、写指针
            _buffer.swap(buffer._buffer);
            std::swap(_write_idx, buffer._write_idx);
            std::swap(_read_idx, buffer._read_idx);
        }

        // 判断缓冲区是否为空
        bool Empty()
        {
            return (_write_idx == _read_idx);
        }

    private:
        // 对写入数据指针进行移动（非暴露接口）
        void RemoveWrite(size_t len)
        {
            // 要求：写指针移动范围不能超过剩余可写入空间大小
            assert(len <= WriteableSize());

            _write_idx += len;
        }

        // 足量扩容
        void ExpansionEnoughSize(size_t len)
        {
            if (len <= WriteableSize())
            {
                // 无需扩容
                return;
            }

            // 如果当前大小低于阈值，采取二倍扩容，否则线性扩容
            size_t newSize = 0;

            // 循环式扩容，确保能存下大小为 len 的数据
            while (WriteableSize() < len)
            {
                if (_buffer.size() < DEFAULT_THRESHOLD)
                    newSize = _buffer.size() == 0 ? 1 : _buffer.size() * 2;
                else
                    newSize = _buffer.size() + LINEAR_GROWTH;

                _buffer.resize(newSize);
            }

            std::cout << "扩容: " << newSize << std::endl;
        }

    private:
        std::vector<char> _buffer; // 缓冲区
        size_t _write_idx;         // 指向写入数据位置的指针（本质是下标）
        size_t _read_idx;          // 指向读取数据位置的指针（本质是下标）
    };
}

#endif